#pragma once
#include <iostream>
#include <string>
#include <cassert>
#include <unordered_map>
#include <fstream>

#include "../comm/log.hpp"
#include "../comm/util.hpp"


namespace ns_model
{
    using namespace ns_log;
    using namespace ns_util;
    using namespace std;
    
    struct Question
    {
        std::string number; //题目的编号，唯一
        std::string title;  //题目的标题  回文串啊
        std::string star;   //题目的难度
        int cpu_limit;
        int mem_limit;
        std::string desc; //题目的描述
        std::string header; //用户编辑的代码
        std::string tail; //题目的测试用例
    };

    const std::string& question_list="./questions/question.list";  //题目列表文件的位置
    const std::string& question_path="./questions/";

    class Model
    {
    private:
        std::unordered_map<std::string,Question> questions;  
    public:
        Model()
        {
            assert(LoadQuestionList); //加载题目，不成功就别玩了
        }

        bool LoadQuestionList(const std::string& question_list)
        {
            std::ifstream in(question_list); 
            if(!in.is_open())
            {
                LOG(ERROR)<<"加载题库失败,请检查是否存在题库⽂件"<<"\n";
                return false;
            }
            
             //1 判断回文数 简单 1 30000  解析的模板
            std::string line;
            while(std::getline(in,line))
            {
                vector<string> tokens;
                StringUtil::SplitString(line,&tokens,"");

                if(tokens.size()!=5) 
                {
                    LOG(WARNING) << "加载部分题⽬失败, 请检查⽂件格式" << "\n";
                }
                Question q;
                q.number=tokens[0];
                q.title=tokens[1];
                q.star=tokens[2];
                q.cpu_limit=atoi(tokens[3].c_str());
                q.mem_limit=atoi(tokens[4].c_str());

                string path=question_path;//questions/1/....
                path+=q.number;//题目的序号
                path+="/";
                FileUtil::ReadFile(path+="desc.txt",&(q.desc),true);//题目的描述
                FileUtil::ReadFile(path+="header.cpp",&(q.header),true);//用户的代码
                FileUtil::ReadFile(path+="tail.cpp",&(q.tail),true);//测试用例

                questions.insert({q.number,q});
            }
            LOG(INFO)<<"加载题库...成功"<<"\n";
            in.close();
        }

        bool GetAllQuestions(vector<Question>*out)//获得所有的题目
        {
            if(questions.size()==0) //题目里面没有题
            {
                LOG(ERROR) << "⽤⼾获取题库失败" << "\n"
                return false; 
            }
            for(auto& q:questions)
            {
                out->insert(q.second);
            }
        }
        
        bool GetOneQuestions(const string& number,Question*q)///获得具体的一个题目
        {
            const auto&iter=questions.find(number);//返回的是一个指针
            if(iter==questions.end());
            {
                LOG(ERROR)<<"他们获取失败，明天编号："<<number<<"\n";
                return false;
            }
            (*q)=iter->second;
        }

    };
};